#include <iostream>
#include <mutex>

#include <benchmark/benchmark.h>

#include "common_affinity.hpp"
#include "workloads.hpp"

// --- 计算类基准 ---
static void BM_Work_Pinned(benchmark::State& state) {
  static std::once_flag pin_flag;
  std::call_once(pin_flag, []() {
    if (!Common::setThreadCore(0)) {
      std::cerr << "[Pinned] 基准线程绑定 core0 失败（将视为未绑定）\n";
    } else {
      std::cerr << "[Pinned] 基准线程已绑定 core0\n";
    }
  });

  volatile double sink = 0.0;
  for (auto _ : state) {
    sink = do_work();
  }
  benchmark::DoNotOptimize(sink);
  state.SetItemsProcessed(static_cast<long long>(state.iterations()));
}

static void BM_Work_Unpinned(benchmark::State& state) {
  static std::once_flag nop_flag;
  std::call_once(nop_flag, []() {
    Common::setThreadCore(-1); // 不做绑定，仅保持接口一致
    std::cerr << "[Unpinned] 基准线程保持默认调度策略\n";
  });

  volatile double sink = 0.0;
  for (auto _ : state) {
    sink = do_work();
  }
  benchmark::DoNotOptimize(sink);
  state.SetItemsProcessed(static_cast<long long>(state.iterations()));
}

// --- 线程切换类基准 ---
static void BM_ThreadSwitch_Pinned(benchmark::State& state) {
  for (auto _ : state) {
    run_thread_switch_ping_pong<true>();
  }
  state.SetItemsProcessed(static_cast<long long>(state.iterations()) *
                          static_cast<long long>(kSwitchesPerIteration));
}

static void BM_ThreadSwitch_Unpinned(benchmark::State& state) {
  for (auto _ : state) {
    run_thread_switch_ping_pong<false>();
  }
  state.SetItemsProcessed(static_cast<long long>(state.iterations()) *
                          static_cast<long long>(kSwitchesPerIteration));
}

BENCHMARK(BM_Work_Pinned)->Unit(benchmark::kMillisecond);
BENCHMARK(BM_Work_Unpinned)->Unit(benchmark::kMillisecond);

BENCHMARK(BM_ThreadSwitch_Pinned)->Unit(benchmark::kMillisecond);
BENCHMARK(BM_ThreadSwitch_Unpinned)->Unit(benchmark::kMillisecond);

BENCHMARK_MAIN();